XNA中Input的检测是放在Update方法中的, 也就是说每一帧都在轮询输入设备1
2
3
4
5
6
7
8
9KeyboardState keyboardState = Keyboard.GetState( );
if (keyboardState.IsKeyDown(Keys.Left))
ringsPosition.X -= ringsSpeed;
if (keyboardState.IsKeyDown(Keys.Right))
ringsPosition.X += ringsSpeed;
if (keyboardState.IsKeyDown(Keys.Up))
ringsPosition.Y -= ringsSpeed;
if (keyboardState.IsKeyDown(Keys.Down))
ringsPosition.Y += ringsSpeed;
这种方式跟Flash或者U3D的使用经验不同, 也和WPF/Winform的开发方式不同.
后者的使用方式类似btn.OnClick += ClickHanlder/btn.addClickListener(ClickHandler)/
btn.addListener(Mouse.Click, ClickHandler)
GitHub上有一个MonoGame-EventDriven-Input项目
https://github.com/ClassicThunder/MonoGame-EventDriven-Input
作者提到轮询方式的缺点:
XNA has a rather severe limitation with regards to handling keyboard input. It is unable detect any keystrokes that occur between pollings. Because of this if your game is updating at the default 60 fps there are 0.017 seconds between polls can be too slow for individual characters of memorized sequences such as “ing”. This method also has the advantage of behaving consistently with other applications, the double click time, character repeat time, etc… are all controlled by your windows settings.
两帧之间的Input检测不到
那它是如何做到Event-driven的? 以下是使用方式1
2
3
4
5
6
7
8
9Input _eventDrivenInput;
_eventDrivenInput = new MonoGameInput(this);
_eventDrivenInput.Update(gameTime);
_eventDrivenInput.KeyDown += (sender, keyDown) =>
{
//Subscribe to the events
};
Using the library is very simple. Simple create an instance of the MonoGameInput object, call Update in the Game.Update function, and then subscribe to the events.
在Game.Update中调用_eventDrivenInput.Update(gameTime);
看MonoGameInput的Update1
2
3
4
5
6
7
8
9
10
11
12
13public sealed class MonoGameInput : Input
{
private readonly MonoGameMouseEvents _mouseEvents;
private readonly MonoGameKeyboardEvents _monoGameKeyboardEvents;
private readonly MonoGameTouchEvents _monoGameTouchEvents;
override public void Update(GameTime gameTime)
{
_mouseEvents.Update(gameTime);
_monoGameKeyboardEvents.Update(gameTime);
_monoGameTouchEvents.Update(gameTime);
}
}
再看MonoGameMouseEvents的Update
1 | internal class MonoGameMouseEvents |
这里仍旧是在Update中遍历Mouse的状态, 依旧是轮询的方式. 只是在使用方式了采取了一种类似event-driven的写法, 不是真正的event-driven吧, 不知道是不是我的理解错了.
那为什么在XNA中是轮询(Polling), 而不是事件驱动(Event Driven)? 其他引擎呢? 像Flash默认是事件监听来响应输入的. 后面的笔记会试图回答这些问题.